package org.ufba.buscador.crawling.preprocessor.simple;

import java.net.URI;
import java.net.URL;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Whitelist;
import org.ufba.buscador.crawling.preprocessor.interfaces.IHTMLPreProcessor;
import org.ufba.buscador.crawling.preprocessor.interfaces.IStopWordsRemover;
import org.ufba.buscador.util.HTMLUtil;


/**
*
* @author Efraim Machado and Arivan Bastos
*/

public class HTMLPreProcessor implements IHTMLPreProcessor 
{	
	private static HTMLPreProcessor instance;
	public static HTMLPreProcessor getInstance()
	{
		if (instance == null)
			instance = new HTMLPreProcessor(new StopWordsRemover());
		
		return instance;
	}
	
	// ----------------------------------------
	
	private IStopWordsRemover stopWordsRemover;
	
	// controls if debug output files are created.
	private boolean debugMode = false;		
	// Debug files path.
	private String debugFilesFolder = "org/ufba/buscador/crawling/preprocessor/resources/debug/";	
	//controls if statistics can be collected and showed
	private boolean showStatistics = false;
	//to cron the time from some call methods
	private long startTimePerMethod;
	//to show statistics
	private StringBuilder statisticBuffer;
	//to use your own stopwords without use a file
	private List<String> stopWords;
		
	public HTMLPreProcessor(IStopWordsRemover stopWordsRemover)
	{
		this.stopWordsRemover = stopWordsRemover;

		URL url = ClassLoader.getSystemResource("");
		debugFilesFolder = url.getPath() + debugFilesFolder;
	}
		
	public IStopWordsRemover getStopWordsRemover() {
		return stopWordsRemover;
	}

	public void setStopWordsRemover(IStopWordsRemover stopWordsRemover) {
		this.stopWordsRemover = stopWordsRemover;
	}
			
	public String clear(URI uri)
	{
		if (uri != null)
		{	
			beginStatisticTimer();
			String htmlContent = HTMLUtil.getHTMLContent(uri);
			endStatisticTimer("GETTING HTML: ");
			
			return clear(htmlContent, true, true);
		}
		return "";
	}
	
	public String clear(URI uri, boolean removeTags, boolean removeStopWords)
	{
		if (uri != null)
		{	
			beginStatisticTimer();
			String htmlContent = HTMLUtil.getHTMLContent(uri);
			endStatisticTimer("GETTING HTML: ");
			
			return clear(htmlContent, removeTags, removeStopWords);
		}
		return "";
	}
	
	public String clear(String text)
	{
		return clear(text, true, true);
	}
	
	public String clear(String htmlContent, boolean removeTags, boolean removeStopWords)
	{	
		if (removeTags)
		{
			/*Efraim Machado - 30/05/2013
			 * Problem: Some docs haven't a space between tags. Ex: <a>myLink</a><a>yourLink</a>.
			 * If we remove that tags some words will be concatened. Ex: myLinkYourLink.   
			 * Solution: add a extra white space after all > symbols.
			 * Side-effect: sometimes double white-spaces happens. No worry, it can be resolved by
			 * replaceAll OR let it to be handled by other layer.
			 */
			beginStatisticTimer();
			htmlContent = htmlContent.replaceAll(">", "> ");
			endStatisticTimer("RESOLVING TAGS EMPTY SPACE: ");

			// Removes HTML tags.
			beginStatisticTimer();
			Document htmlDoc = Jsoup.parse(htmlContent);
			htmlContent = htmlDoc.text();
			endStatisticTimer("REMOVING HTML TAGs: ");
		}
		
		if (removeStopWords)
		{
			beginStatisticTimer();
			if (stopWords != null)
				stopWordsRemover.setStopWords(stopWords);
			htmlContent = stopWordsRemover.removeStopWords(htmlContent);
			endStatisticTimer("REMOVING STOPWORDS: ");
		}

		return htmlContent;
	}
	
	public void printStatistics()
	{
		System.out.println("[HTMLPreProcessor]\n" + statisticBuffer.toString());
	}
	
	// ---------------------------------------------------------------------------------
	
	public void resetStatistics()
	{
		statisticBuffer = new StringBuilder();
	}
	
	public void beginStatisticTimer()
	{
		if (showStatistics)
			startTimePerMethod = System.currentTimeMillis();  
	}
	
	public void endStatisticTimer(String message)
	{
		if (showStatistics)
			statisticBuffer.append(message + (System.currentTimeMillis()-startTimePerMethod) + "ms.\n");
	}
	
	// ---------------------------------------------------------------------------------
	
	public List<String> getStopWords() 
	{
		return stopWords;
	}

	public void setStopWords(List<String> stopWords) 
	{
		this.stopWords = stopWords;
	}

	public boolean isShowStatistics() 
	{
		return showStatistics;
	}

	public void setShowStatistics(boolean showStatistics) 
	{
		this.showStatistics = showStatistics;
	}
	
	public void setDebugMode(boolean debugMode)
	{
		this.debugMode = debugMode;
	}
}
